import type {
  CalculationStrategy,
  WetAirState,
  WetAirStateParameter,
  WetAirStateKeys
} from '../types'

/**
 * ### 策略模式基础抽象类实现计算策略接口
 */
abstract class BaseStrategy implements CalculationStrategy {
  /**
   * #### 验证参数是否包含所需的字符串
   * @param params 参数
   * @param requireKeys 必传的参数key
   */
  protected validateParams<T extends WetAirStateKeys>(
    params: WetAirStateParameter,
    requireKeys: T[]
  ): asserts params is WetAirStateParameter & Record<T, number> {
    // 类型守卫：检查参数是否包含所需的属性
    const hasAllKeys =
      requireKeys.length &&
      requireKeys.every((key) =>
        Object.prototype.hasOwnProperty.call(params, key)
      )
    if (!hasAllKeys) {
      throw new Error(
        `required parameters:${requireKeys.join(',')} must be provided`
      )
    }
  }

  /**
   * 规范化含湿量，如果含湿量在0.5到300之间，则将其除以1000
   * @param humidity 含湿量
   * @returns
   */
  protected normalizeHumidity(humidity: number): number {
    return humidity >= 0.5 && humidity <= 300 ? humidity / 1000 : humidity
  }

  /**
   * #### 验证温度大小顺序
   * 干球温度>=湿球温度>=露点温度
   * @param lower 低的值
   * @param higher 高的值
   * @param lowerName 低的值名称
   * @param higherName 高的值名称
   */
  protected validateTemperatureOrder(
    lower: number,
    higher: number,
    lowerName: string,
    higherName: string
  ) {
    if (lower > higher) {
      throw new Error(`${lowerName} must be less than ${higherName}`)
    }
  }

  /**
   * #### 计算湿空气状态，抽象方法，通过子类实现
   * @param params 湿空气传入的状态参数，只能传2个
   * @param pressure 大气压力，单位：KPa
   */
  abstract calculate(
    params: WetAirStateParameter,
    pressure: number
  ): WetAirState
}

export default BaseStrategy
